package org.elec.mac.fliter;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elec.mac.ehcache.CacheConfiguration;
import org.elec.mac.ehcache.ManageEhCache;
import org.elec.mac.entity.OAuthToken;
import org.elec.mac.utils.Utils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCacheManager;

import java.io.IOException;
import java.util.Calendar;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

@Slf4j
@WebFilter(filterName = "CheckSessionFilter", urlPatterns = "*.do", description = "System Filter")
public class CheckSessionFilter implements Filter {

    protected FilterConfig filterConfig = null;

    @Autowired
    private ManageEhCache manageEhCache;

    @Autowired
    private CacheConfiguration cacheConfiguration;

    private EhCacheCacheManager manager;

    @Value("${web.filter.system}")
    public String systemPass;

    @Value("${tencent.wx.api}")
    private String url;

    @Value("${tencent.wx.secret}")
    private String secret;

    @Value("${tencent.wx.appid}")
    private String appid;

    @Value("${tencent.wx.refresh}")
    private String refresh_url;

    @Value("${tencent.wx.tokenurl}")
    private String tokenurl;

    @Value("${tencent.wx.jsapiurl}")
    private String jsapiurl;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        manageEhCache.cacheInit();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hsrq = (HttpServletRequest) request;
        HttpServletResponse hsrp = (HttpServletResponse) response;
        hsrp.setContentType("text/html; charset=UTF-8");
        hsrp.setHeader("Access-Control-Allow-Origin", "*");
        hsrp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        hsrp.setHeader("Access-Control-Max-Age", "3600");
        hsrp.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        String user_agent = hsrq.getHeader("User-Agent");
        String reqPage = StringUtils.trim(hsrq.getServletPath());
        if(reqPage.startsWith("/")) {
            reqPage = reqPage.substring(1);
        }
        log.info(reqPage);
        manager = cacheConfiguration.ehCacheCacheManager(cacheConfiguration.ehCacheManagerFactoryBean());

        if(filterPass(systemPass, reqPage)) {
            chain.doFilter(request, response);
        } else {
            /*boolean redirect = false;
            if(user_agent.contains("AlipayClient")) {
                redirect = this.alipay(hsrq, hsrp);
            } else if(user_agent.contains("MicroMessenger")) {
                redirect = this.wxPay(hsrq, hsrp);
            } else {
                // 重定向值错误引导页面
                hsrp.sendRedirect("/refuse.html");
            }
            if(!redirect) {
                hsrp.sendRedirect("/index.do?mach=1");
                return;
            }*/
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }

    /**
     * 微信鉴权
     *
     * @param hsrq
     * @param hsrp
     * @return
     */
    public boolean wxPay(HttpServletRequest hsrq, HttpServletResponse hsrp) throws IOException {
        String openid = hsrq.getParameter("openid");
        String code = hsrq.getParameter("code");
        if (StringUtils.isNotBlank(code)) {
            return true;
        }
        if (StringUtils.isBlank(openid)) {
            return false;
        }
        Cache authTokenCache = manager.getCache("authTokenCache");
        OAuthToken authToken = authTokenCache.get(openid, OAuthToken.class);
        if(authToken == null) {
            return false;
        }
        Calendar calendar = Calendar.getInstance();
        Long expires_in = Utils.parseLong(authToken.getExpires_in(), 0L);
        if(expires_in == 0L) {
            log.error("expires_in转换错误");
            return false;
        }
        // 时间判断
        if(calendar.getTimeInMillis() - authToken.getLogin_time() > expires_in * 1000) {
            OkHttpClient httpClient = new OkHttpClient();
            RequestBody body = new FormBody.Builder().add("appid", appid)
                    .add("secret", secret)
                    .add("refresh_token", authToken.getRefresh_token())
                    .add("grant_type", "refresh_token").build();
            Request req = new Request.Builder().url(refresh_url).post(body).build();
            Response resp = httpClient.newCall(req).execute();
            authTokenCache.evict(openid);
            if(resp.isSuccessful()) {
                JSONObject responseBody = new JSONObject(resp.body().string());
                openid = (String) responseBody.get("openid");
                authToken.setAccess_token((String) responseBody.get("access_token"));
                authToken.setExpires_in(responseBody.get("expires_in").toString());
                authToken.setLogin_time(System.currentTimeMillis());
                authToken.setOpenid(openid);
                authToken.setRefresh_token(responseBody.get("refresh_token").toString());
                authToken.setScope((String) responseBody.get("scope"));
            }
            body = new FormBody.Builder()
                    .add("appid", appid).add("secret", secret)
                    .add("grant_type", "client_credential").build();
            req = new Request.Builder().url(tokenurl).post(body).build();
            resp = httpClient.newCall(req).execute();
            // 重新获取jsapi鉴权信息
            if(resp.isSuccessful()) {
                JSONObject responseBody = new JSONObject(resp.body().string());
                String cgi_token = (String) responseBody.get("access_token");
                authToken.setCgi_token(cgi_token);
                body = new FormBody.Builder().add("access_token", cgi_token).add("type", "jsapi").build();
                req = new Request.Builder().url(jsapiurl).post(body).build();
                resp = httpClient.newCall(req).execute();
                if(resp.isSuccessful()) {
                    JSONObject responseBody2 = new JSONObject(resp.body().string());
                    authToken.setTicket((String) responseBody2.get("ticket"));
                }
            }
            // 更新缓存
            authTokenCache.put(openid, authToken);
        }
        return true;
    }

    /**
     * 阿里鉴权
     *
     * @param hsrq
     * @param hsrp
     * @return
     */
    public boolean alipay(HttpServletRequest hsrq, HttpServletResponse hsrp) {
        return false;
    }

    /**
     * 路径通行证
     *
     * @param filterPath
     * @param reqPage
     * @return
     */
    public boolean filterPass(String filterPath, String reqPage) {
        String[] path = filterPath.split(",");
        if(ArrayUtils.contains(path, reqPage)) {
            return true;
        } else if(reqPage.indexOf("/") >= 0 && ArrayUtils.contains(path, reqPage.substring(0, reqPage.indexOf("/")))) {
            return true;
        }
        return false;
    }
}